package com.huiquan.icd.service;

import com.huiquan.analysis.domain.User;
import com.huiquan.foundation.constant.RoleID;
import com.huiquan.foundation.dao.PaginationDao;
import com.huiquan.foundation.domain.Pagination;
import com.huiquan.foundation.service.PaginationService;
import com.huiquan.foundation.service.UserRecordService;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.utils.CollectionUtil;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.icd.dao.IcdDiseaseSymptomDao;
import com.huiquan.icd.domain.IcdDiseaseSymptom;
import com.huiquan.management.dao.UserAbilityDao;
import com.huiquan.management.domain.UserAbility;
import com.huiquan.management.service.UserAbilityService;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.*;
import com.huiquan.framework.utils.EMailUtil;


@Service
public class IcdDiseaseSymptomService extends BaseService {
	@Autowired
	private PaginationService paginationService;
	@Autowired
	private UserAbilityService userAbilityService;
	@Autowired
	private IcdDiseaseSymptomDao icdDiseaseSymptomDao;
	@Autowired
	private UserAbilityDao userAbilityDao;
	@Autowired
	private PaginationDao paginationDao;
	@Autowired
	private UserRecordService userRecordService;
    @Autowired
    private EMailUtil eMailUtil;

	private static double PASS_SCORE = 0.15;

	public ModelAndView list(Integer startStr, String keyword,String keyword2, String flag, String countPerPageStr, User user,
			String checkFlag, String type, String exactSearchFlag,String exactSearchFlag2, HttpServletResponse resp, HttpServletRequest req,String searchOwner)
			throws Exception {
		Map<String, Object> param = new HashMap<>();
		boolean exactFlag = exactSearchFlag != null && exactSearchFlag.equals("1");
		boolean exactFlag2 = exactSearchFlag2 != null && exactSearchFlag2.equals("1");

		if (keyword != null && !keyword.isEmpty()) {
			param.put("keyword", exactFlag ? keyword : "%" + keyword + "%");
		}
		if (keyword2 != null && !keyword2.isEmpty()) {
			if("symptom".equals(type)){
				param.put("example", exactFlag2 ? keyword2 : "%" + keyword2 + "%");
			}else{
				param.put("keyword2", exactFlag2 ? keyword2 : "%" + keyword2 + "%");
			}
		}
		int totalSize = 0, start = 0, endPage = 0, startIndex = 0;
		List<IcdDiseaseSymptom> list = new ArrayList<>();
		// 判断是否经过测试
		Map<String, Object> abilityParam = new HashMap<>();
		abilityParam.put("userId", user.getUserId());
		abilityParam.put("roleId", user.getRole());
		// 如果是管理员则直接进入功能界面不需要测试
		UserAbility ability = null;
		if (user.getRole() == 1) {
			ability = new UserAbility();
			ability.setExamPass(1);
		} else {
			ability = userAbilityDao.retrieveObjectByMap(abilityParam);
		}
		if (ability == null) {
			// 未配置则进入错误界面
			userAbilityService.incapable(resp, req);
			return null;
		}
		// 未校验
		if ("0".equals(checkFlag) && ("o".equals(type) || "s".equals(type))) {
			// S 需要进入测试
			if (ability.getExamPass() == -1 && "s".equals(type)) {
				// 未完成测试,进入测试
				// 判断是否有测试数据生成
				param.put("ownerId", user.getUserId());
				int count = icdDiseaseSymptomDao.retrieveTestSize(param);
				if (count < 1) {
					// 初始化测试数据
					icdDiseaseSymptomDao.initSTestData(user.getUserId());
				}
				param.put("checkFlag", "0");
				param.put("type", type);
				param.put("order", "b.disease_name");
				totalSize = icdDiseaseSymptomDao.retrieveTestSize(param);
				Map<String, Integer> pageNo = new HashMap<>();
				pageNo = GetListUtil.getPageNoParam(totalSize, startStr + "");
				endPage = pageNo.get("endPage");
				start = pageNo.get("start");
				startIndex = pageNo.get("startIndex");
				if (startIndex < totalSize) {
					param.put("startIndex", startIndex);
					list = icdDiseaseSymptomDao.retrieveTestList(param);
				}
				for (IcdDiseaseSymptom value : list) {
					if (StringUtils.isNotBlank(value.getExample())) {
						value.setShowExample(value.getExample().replace((char) 1 + "", "\n"));
						value.setExample(value.getExample().split((char) 1 + "")[0]);
					}
				}
			} else if (ability.getExamPass() == 0 && "s".equals(type)) {
				// 未通过进入错误页面
				userAbilityService.incapable(resp, req);
			} else {
				// 正式功能
				// 获取当前页码
				endPage = icdDiseaseSymptomDao.retrieveTotalPageNo(user.getRole() == 1 ? "" : (user.getUserId() + ""),
						type);
				if (endPage < 1) {
					endPage = 1;
				}
				start = startStr == null ? 1 : startStr;
				if (start > endPage) {
					start = endPage;
				}

				// 获取页码对应的排序字段
				param.put("start", start - 1);
				param.put("ownerId", user.getRole() == 1 ? "" : user.getUserId());
				if ("s".equals(type)) {
					param.put("typeS", type);
				} else {
					param.put("type", type);
				}
				// 获取页码
				Map<String, String> orderDiseaseIdMap = icdDiseaseSymptomDao.retrievePageOrderVocabulary(param);
				String orderDiseaseId = null;
				String typeFlag = null;
				if (orderDiseaseIdMap != null) {
					orderDiseaseId = orderDiseaseIdMap.get("disease_name");
					typeFlag = orderDiseaseIdMap.get("type");
				}
				if (orderDiseaseId != null && !orderDiseaseId.isEmpty()) {
					List<String> diseaseName = CollectionUtil
							.getListByArray(orderDiseaseId.substring(1, orderDiseaseId.length()).split((char) 1 + ""));
					// 根据页码获取列表
					if ("o".equals(type)) {
						list = getDiseaseSymptomNoCheckList(diseaseName);
					} else {
						list = icdDiseaseSymptomDao.retrieveDiseaseByTypeAndDiseaseName(diseaseName, typeFlag);
						for (IcdDiseaseSymptom value : list) {
							if (StringUtils.isNotBlank(value.getExample())) {
								value.setShowExample(value.getExample().replace((char) 1 + "", "\n"));
								value.setExample(value.getExample().split((char) 1 + "")[0]);
							}
						}
					}
				}
			}

		} else {
			// 测试
			if (ability.getExamPass() == -1 && "s".equals(type)) {
				// 未完成测试,进入测试
				// 判断是否有测试数据生成
				param.put("ownerId", user.getUserId());
				int count = icdDiseaseSymptomDao.retrieveTestSize(param);
				if (count < 1) {
					// 初始化测试数据
					icdDiseaseSymptomDao.initSTestData(user.getUserId());
				}
				if (StringUtils.isNotBlank(flag)) {
					param.put("flag", flag);
				}
				param.put("checkFlag", "1");
				param.put("type", type);
				param.put("order", "b.gmt_modified");
				totalSize = icdDiseaseSymptomDao.retrieveTestSize(param);
				Map<String, Integer> pageNo = new HashMap<>();
				pageNo = GetListUtil.getPageNoParam(totalSize, startStr + "");
				endPage = pageNo.get("endPage");
				start = pageNo.get("start");
				startIndex = pageNo.get("startIndex");
				if (startIndex < totalSize) {
					param.put("startIndex", startIndex);
					list = icdDiseaseSymptomDao.retrieveTestList(param);
				}
				for (IcdDiseaseSymptom value : list) {
					if (StringUtils.isNotBlank(value.getExample())) {
						value.setShowExample(value.getExample().replace((char) 1 + "", "\n"));
						value.setExample(value.getExample().split((char) 1 + "")[0]);
					}
				}
			} else {
				// 已校验
				param.put("checkFlag", checkFlag);
				if ("s".equals(type)) {
					param.put("typeS", type);
				} else {
					param.put("type", type);
				}
				if (StringUtils.isNotBlank(flag) && "2".equals(flag)) {
					param.put("flagAll", flag);
				} else if (StringUtils.isNotBlank(flag)) {
					param.put("flag", flag);
				}
				if ("1".equals(checkFlag)) {
					param.put("order", "b.gmt_modified desc");
				} else {
					param.put("order", "b.disease_name");
				}
				if(StringUtils.isNotBlank(searchOwner)){
					param.put("ownerName",searchOwner);
					param.put("order", "b.disease_name");
				}else{
					param.put("ownerId", user.getRole() == 1 ? "" : user.getUserId());
				}
				totalSize = icdDiseaseSymptomDao.retrieveSize(param);
				Map<String, Integer> pageNo = new HashMap<>();
				if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
					int countPerPage = Integer.parseInt(countPerPageStr);
					pageNo = GetListUtil.getPageNoParam(totalSize, startStr + "", countPerPage);
					param.put("countPerPage", countPerPage);
				} else {
					pageNo = GetListUtil.getPageNoParam(totalSize, startStr + "");
				}

				endPage = pageNo.get("endPage");
				start = pageNo.get("start");
				startIndex = pageNo.get("startIndex");
				if (startIndex < totalSize) {
					param.put("startIndex", startIndex);
					list = icdDiseaseSymptomDao.retrieveList(param);
				}
				for (IcdDiseaseSymptom value : list) {
					if (StringUtils.isNotBlank(value.getExample())) {
						value.setShowExample(value.getExample().replace((char) 1 + "", "\n"));
						value.setExample(value.getExample().split((char) 1 + "")[0]);
					}
				}
			}
		}

		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
		if (!("0".equals(checkFlag) && ("o".equals(type) || "s".equals(type)))) {
			Map<String, String> showSearch = new LinkedHashMap<>();
			showSearch.put("keyword", "疾病");
			showSearch.put("keyword2", "症状");
			// 如果是操作员可以搜索拥有者的数据
			if(user.getRole() == 1){
				showSearch.put("searchOwner","拥有者");
			}
			Map<String, String> searchMap = new HashMap<>();
			searchMap.put("keyword", keyword);
			searchMap.put("keyword2",keyword2);
			searchMap.put("searchOwner",searchOwner);
			map.put("showSearch", showSearch);
			map.put("showSearchValue", searchMap);

		}

		if (ability.getExamPass() == -1 && "s".equals(type)) {
			map.put("testFlag", "1");
		} else {
			map.put("testFlag", "0");
		}

		return new ModelAndView("icd/index", map);
	}

	public List<IcdDiseaseSymptom> getDiseaseSymptomNoCheckList(List<String> diseaseNames) {
		// 该页所有疾病名称
		List<IcdDiseaseSymptom> showList = new ArrayList<>();
		for (String diseaseName : diseaseNames) {
			// 查询该疾病下未校验的o,o的上下级line
			Map<String, Object> param = new HashMap<>();
			param.put("checkFlag", 0);
			param.put("diseaseName", diseaseName);
			List<IcdDiseaseSymptom> diseaseSymptoms = icdDiseaseSymptomDao.retrieveDiseaseOOrderList(param);
			// 最后一级的列表
			List<IcdDiseaseSymptom> haveNoNext = new ArrayList<>();
			// 有下级的列表
			List<IcdDiseaseSymptom> haveNext = new ArrayList<>();
			// 按有无下级分类
			for (IcdDiseaseSymptom diseaseSymptom : diseaseSymptoms) {
				if (diseaseSymptom.getLineFlag() == 1) {
					haveNext.add(diseaseSymptom);
				} else if (diseaseSymptom.getLineFlag() == 0) {
					haveNoNext.add(diseaseSymptom);
				}
			}
			// 循环没有下级的需要把上级填上
			for (IcdDiseaseSymptom diseaseSymptom : haveNoNext) {
				List<IcdDiseaseSymptom> lineList = new ArrayList<>();
				Long id = diseaseSymptom.getId();
				String line = diseaseSymptom.getLine();
				lineList.add(diseaseSymptom);
				StringBuffer showIds = new StringBuffer();
				String showFlag = "0";
				for (IcdDiseaseSymptom ds : haveNext) {
					// 如果这个上级有这个最下级,需要放入一个list
					if (ds.getGroupId().contains(id + "")) {
						lineList.add(ds);
						if (ds.getFlag() == 1) {
							showFlag = "1";
						}
					}
				}
				if (diseaseSymptom.getFlag() == 1) {
					showFlag = "1";
				}
				// 根据line 给lineList排序
				lineList = sortLineList(lineList, line, showIds);
				diseaseSymptom.setShowFlag(showFlag);
				diseaseSymptom.setLineList(lineList);
				diseaseSymptom.setShowIds(showIds.toString().substring(0, showIds.length() - 1));
			}
			showList.addAll(haveNoNext);
		}

		return showList;

	}

	private List<IcdDiseaseSymptom> sortLineList(List<IcdDiseaseSymptom> lineList, String line, StringBuffer showIds) {
		List<IcdDiseaseSymptom> sortList = new ArrayList<>();
		String[] words = line.substring(1, line.length()).split("-");
		for (String word : words) {
			for (IcdDiseaseSymptom ds : lineList) {
				if (StringUtils.isNotBlank(word) && word.equals(ds.getVocabulary())) {
					ds.setExample(ds.getExample().replace((char) 1 + "", "\n"));
					sortList.add(ds);
					showIds.append(ds.getId()).append(",");

				}
			}
		}
		return sortList;
	}

	/**
	 * 初始化疾病症状的o的分页 (只生成一次)
	 */
	public void initOrderOSymptom() {
		LOGGER.info("initOrderOSymptom begin");
		// 查询出疾病对应的code的条数在未校验中
		List<Map<String, Object>> diseaseCodeCounts = icdDiseaseSymptomDao.retrieveDisSymptomOOrderList();
		List<Pagination> addOrderValue = initOrder(diseaseCodeCounts, "o");
		addOrderValue = paginationService.averagePaging(addOrderValue, RoleID.DISEASE_SYMPTOM_O_CHECK.getId());
		if (addOrderValue != null && addOrderValue.size() > 0) {
			paginationDao.insertBatch(addOrderValue);
		}

		// 更新未校验数据的拥有人(在初始化s分包之后一起更新)
		LOGGER.info("initOrderOSymptom end");

		// 初始化s
		LOGGER.info("initOrderSSymptom begin");
		initSSymptom();
		LOGGER.info("initOrderSSymptom end");
		
		//未校验数据大于800条时发邮件       
        int countUnchecked = icdDiseaseSymptomDao.retrieveUncheckedDisease();
        if (countUnchecked>800) {
            try {
            	String subject="初始化疾病和症状黑白名单时，未校验数据为"+countUnchecked+"条";
    			List<String> address = new ArrayList<>();
    			address.add("fq@witspring.com");
                eMailUtil.sendBatchEmail("", subject, address);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }

	}
	
	public ReturnData changeFlag(String ids, String flag, User user) {
		// 判断是否是测试数据
		Map<String, Object> abilityParam = new HashMap<>();
		abilityParam.put("userId", user.getUserId());
		abilityParam.put("roleId", user.getRole());
		// 如果是管理员则直接进入功能界面不需要测试
		UserAbility ability = null;
		if (user.getRole() == 1) {
			ability = new UserAbility();
			ability.setExamPass(1);
		} else {
			ability = userAbilityDao.retrieveObjectByMap(abilityParam);
		}
		if (ability.getExamPass() == 1) {
			// 如果已经测试通过则是正式数据
			Map<String, Object> param = new HashMap<>();
			param.put("ids", ids);
			param.put("flag", flag);
			param.put("userId", user.getUserId());
			icdDiseaseSymptomDao.updateFlag(param);
		} else {
			// 测试数据
			Map<String, Object> param = new HashMap<>();
			param.put("ids", ids);
			param.put("flag", flag);
			param.put("userId", user.getUserId());
			icdDiseaseSymptomDao.updateTestFlag(param);
		}
		return ReturnUtil.success();
	}

	public ReturnData submitPage(String ids, User user, String start, String type) {
		if (ids == null || ids.isEmpty()) {
			ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
			rc.setDesc("该模块数据已全部校验完成！");

			return ReturnUtil.fail(rc);
		}
		Map<String, Object> abilityParam = new HashMap<>();
		abilityParam.put("userId", user.getUserId());
		abilityParam.put("roleId", user.getRole());
		// 如果是管理员则直接进入功能界面不需要测试
		UserAbility ability = null;
		if (user.getRole() == 1) {
			ability = new UserAbility();
			ability.setExamPass(1);
		} else {
			ability = userAbilityDao.retrieveObjectByMap(abilityParam);
		}
		if (ability.getExamPass() == 1) {
			// 正式数据
			Map<String, Object> param = new HashMap<>();
			param.put("ids", ids.substring(0, ids.length() - 1));
			param.put("userId", user.getUserId());
			icdDiseaseSymptomDao.updateCheckFlag(param);
			// 管理员不需要统计
			userRecordService.addUpUserRecord(user.getUserId(), ids.substring(0, ids.length() - 1).split(",").length);
			// 判断是否没有数据
			if ("o".equals(type) || "s".equals(type)) {
				Map<String, Object> param1 = new HashMap<>();
				param1.put("start", Long.parseLong(start) - 1);
				param1.put("ownerId", user.getRole() == 1 ? "" : user.getUserId());
				if ("s".equals(type)) {
					param1.put("typeS", type);
				} else {
					param1.put("type", type);
				}
				Map<String, String> orderDiseaseIdMap = icdDiseaseSymptomDao.retrievePageOrderVocabulary(param1);
				String orderDiseaseId = null;
				String typeFlag = null;
				if (orderDiseaseIdMap != null) {
					orderDiseaseId = orderDiseaseIdMap.get("disease_name");
					typeFlag = orderDiseaseIdMap.get("type");
				}
				List<IcdDiseaseSymptom> list = new ArrayList<>();
				if (orderDiseaseId != null && !orderDiseaseId.isEmpty()) {
					List<String> diseaseName = CollectionUtil
							.getListByArray(orderDiseaseId.substring(1, orderDiseaseId.length()).split((char) 1 + ""));
					// 根据页码获取列表
					if ("o".equals(type)) {
						list = getDiseaseSymptomNoCheckList(diseaseName);
					} else {
						list = icdDiseaseSymptomDao.retrieveDiseaseByTypeAndDiseaseName(diseaseName, typeFlag);
					}
				}
				if (list.size() == 0) {
					// 需要把分页改成已校验
					param.clear();
					param.put("id", ids.split(",")[0]);
					param.put("type", typeFlag);
					param.put("uid", user.getUserId());
					icdDiseaseSymptomDao.updateOrderFlag(param);
				}
			}
		} else {
			// 测试数据
			Map<String, Object> param = new HashMap<>();
			param.put("ids", ids.substring(0, ids.length() - 1));
			param.put("userId", user.getUserId());
			icdDiseaseSymptomDao.updateTestCheckFlag(param);
			// 判断是否已经完成所有的校验
			param.clear();
			param.put("checkFlag", "0");
			param.put("type", type);
			param.put("ownerId", user.getUserId());
			int count = icdDiseaseSymptomDao.retrieveTestSize(param);
			if (count == 0) {
				// 开始计算成绩
				param.clear();
				param.put("type", type);
				param.put("ownerId", user.getUserId());
				// 总数
				int cnt = icdDiseaseSymptomDao.retrieveTestSize(param);
				// 错误的数量
				param.clear();
				param.put("type", type);
				param.put("uid", user.getUserId());
				int wrongCnt = icdDiseaseSymptomDao.checkTestWrongSize(param);
				double proportion = (double) wrongCnt / cnt;
				if (proportion > PASS_SCORE) {
					// 正确率不行,失败,循环重新测试
					icdDiseaseSymptomDao.deleteTestDataByOwner(user.getUserId(), "s");
					return ReturnUtil.success("测验未通过，将重新获取数据进行测验！");
				} else {
					// 正确率可以,通过
					userAbilityDao.updatePassFlagByUidAndRole(1, user.getUserId(), user.getRole());
					userAbilityService.pass(user);
					return ReturnUtil.success("测验通过，开始获取正式数据！");

				}
			}

		}
		return ReturnUtil.success("");
	}

	/**
	 * 初始化s的分包 si的分包
	 */
	public void initSSymptom() {
		// 所有需要排序的s
		List<Map<String, Object>> diseaseCodeCounts = icdDiseaseSymptomDao.retrieveDisSymptomSOrderList();
		// 所有的分页
		List<Pagination> addOrderValue = initOrder(diseaseCodeCounts, "s");

		addOrderValue = paginationService.averagePaging(addOrderValue, RoleID.DISEASE_SYMPTOM_S_CHECK.getId());
		if (addOrderValue != null && addOrderValue.size() > 0) {
			paginationDao.insertBatch(addOrderValue);
		}

		// 加入si的分包
		List<Map<String, Object>> siCounts = icdDiseaseSymptomDao.retrieveDisSymptomSiOrderList();
		List<Pagination> siOrderValue = initOrder(siCounts, "si");
		siOrderValue = paginationService.averagePaging(siOrderValue, RoleID.DISEASE_SYMPTOM_S_CHECK.getId());
		if (siOrderValue != null && siOrderValue.size() > 0) {
			paginationDao.insertBatch(siOrderValue);
		}

		// 更新所有的拥有人(包括o)
		icdDiseaseSymptomDao.updateSymptomOwner();

	}

	private List<Pagination> initOrder(List<Map<String, Object>> diseaseCodeCounts, String type) {
		long sum = 0;
		StringBuffer disease = new StringBuffer();
		long num = 1;
		List<Pagination> addOrderValue = new ArrayList<>();
		for (Map<String, Object> value : diseaseCodeCounts) {
			String diseaseId = value.get("disease_name") + "";
			long count = Long.parseLong(value.get("count") + "");
			// 说明是第一个
			sum += count;
			// 如果第一个就>20就直接添加
			if (sum > 20) {
				Pagination orderValue = new Pagination();
				orderValue.setOrderParam(disease.append((char) 1).append(diseaseId).toString());
				orderValue.setFlag(-1);
				orderValue.setPageNo(num);
				orderValue.setType(type);
				addOrderValue.add(orderValue);
				num++;
				disease = new StringBuffer();
				sum = 0;
			} else {
				disease.append((char) 1).append(diseaseId);
			}
		}
		// 保存最后组
		if (sum > 0 && StringUtils.isNotBlank(disease.toString())) {
			Pagination orderValue = new Pagination();
			orderValue.setOrderParam(disease.toString());
			orderValue.setFlag(-1);
			orderValue.setPageNo(num);
			orderValue.setType(type);
			addOrderValue.add(orderValue);
			num++;
			disease = new StringBuffer();
			sum = 0;
		}
		return addOrderValue;

	}

}
